home *** CD-ROM | disk | FTP | other *** search
- // BEGIN FLOCK GPL
- //
- // Copyright Flock Inc. 2005-2007
- // http://flock.com
- //
- // This file may be used under the terms of of the
- // GNU General Public License Version 2 or later (the "GPL"),
- // http://www.gnu.org/licenses/gpl.html
- //
- // Software distributed under the License is distributed on an "AS IS" basis,
- // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- // for the specific language governing rights and limitations under the
- // License.
- //
- // END FLOCK GPL
-
- var EXPORTED_SYMBOLS = ["onlineFavoritesBackend"];
-
- const CC = Components.classes;
- const CI = Components.interfaces;
- const CR = Components.results;
- const CU = Components.utils;
-
- CU.import("resource:///modules/FlockScheduler.jsm");
-
- /**************************************************************************
- * Module: Online Favorites Back End
- **************************************************************************/
-
- /* Note: This module depends on access to the following PRIVATE properties
- of the services being supported:
- - aService._coop
- - aService._logger
- - aService._c_svc
- */
-
- // Bookmark stream refresh interval in seconds.
- const DEFAULT_REFRESH_INTERVAL = 5 * 60;
- const PREF_ONLINEFAVE_REFRESH_INTERVAL = "flock.favorites.online.refreshInterval";
-
- CC["@mozilla.org/moz/jssubscript-loader;1"]
- .getService(CI.mozIJSSubScriptLoader)
- .loadSubScript("chrome://flock/content/common/flocksafe.js");
-
-
- /**************************************************************************
- * Private Data and Functions
- **************************************************************************/
-
- // Helper function to assist in comparing strings.
- function stringify(aObj) {
- if (!aObj) {
- return "";
- } else {
- return aObj;
- }
- }
-
- // Helper function to assist in comparing dates.
- function dateify(aObj) {
- if (!aObj) {
- return 0;
- } else {
- return aObj.getTime();
- }
- }
-
- // Helper function to assist in comparing lists of tags.
- function sanitizeTags(aTagList) {
- return aTagList ? aTagList.split(/[\s,]/).sort().join(",") : "";
- }
-
- // Helper function to assist in comparing complete bookmarks.
- function bookmarks_match(bm1, bm2) {
- return (bm1.private === bm2.private && /* booleans - nice and easy */
- stringify(bm1.name) === stringify (bm2.name) &&
- stringify(bm1.description) === stringify(bm2.description) &&
- sanitizeTags(bm1.tags) === sanitizeTags(bm2.tags) &&
- dateify(bm1.datevalue) === dateify(bm2.datevalue));
- }
-
-
- /**************************************************************************
- * Online Favorites Back End Public Interface
- **************************************************************************/
-
- var onlineFavoritesBackend = {};
-
- onlineFavoritesBackend.createAccount =
- function OFBE_createAccount(aService, aAccountID, aIsTransient) {
- var account_urn = aService.urn + ":" + aAccountID;
- var account;
- if (!aService._coop.Account.exists(account_urn)) {
- account = new aService._coop.Account(account_urn, {
- name: aAccountID,
- serviceId: aService.contractId,
- service: aService._c_svc,
- accountId: aAccountID,
- favicon: aService.icon,
- URL: aService.getUserUrl(aAccountID),
- isTransient: aIsTransient,
- showInSidebar: false
- });
- aService._coop.accounts_root.children.addOnce(account);
- } else {
- account = aService._coop.get(account_urn);
- }
-
- // Create a "stream" for the online bookmarks
- var bookmarks = {};
- var bookmarks_urn = account_urn + ":bookmarks";
- if (!aService._coop.OnlineBookmarksStream.exists(bookmarks_urn)) {
- prefService = CC["@mozilla.org/preferences-service;1"]
- .getService(CI.nsIPrefBranch);
- var prefRefreshInterval = DEFAULT_REFRESH_INTERVAL;
- if (prefService.getPrefType(PREF_ONLINEFAVE_REFRESH_INTERVAL)) {
- prefRefreshInterval = prefService.getIntPref(PREF_ONLINEFAVE_REFRESH_INTERVAL);
- }
-
- bookmarks = new aService._coop.OnlineBookmarksStream(bookmarks_urn, {
- name: aAccountID + " on " + aService.title,
- userid: aAccountID,
- serviceId: aService.contractId,
- favicon: aService.icon,
- isTransient: aIsTransient,
- refreshInterval: prefRefreshInterval
- });
- aService._coop.onlinebookmarks_root.children.addOnce(bookmarks);
- }
-
- // Create the "no tag" folder
- var noTagFolder = new aService._coop.Folder(bookmarks.id() + ":notag", {
- name: flockGetString("favorites/favorites", "flock.favs.online.noTag")
- });
- bookmarks.children.add(noTagFolder);
-
- var acct = aService.getAccount(account_urn);
- return acct;
- };
-
- onlineFavoritesBackend.removeAccount =
- function OFBE_removeAccount(aService, aAccountUrn) {
- var acctCoopObj = aService._coop.get(aAccountUrn);
- var parents = {};
- var i;
- // Next delete the bookmarks that are solely associated with this account
- var bookmarks_urn = aAccountUrn + ":bookmarks";
- var bmStream = aService._coop.get(bookmarks_urn);
- if (bmStream) {
- aService._logger.debug("found bookmark stream " + bookmarks_urn);
- // Remove the Delicious Bookmarks node from its parents
- parents = bmStream.getParents();
- for (i = 0; i < parents.length; i++) {
- parents[i].children.remove(bmStream);
- }
- } else {
- aService._logger.debug("DID NOT find bookmark stream " + bookmarks_urn);
- }
- // Next remove the account from any parents it might have
- parents = acctCoopObj.getParents();
- for (i = 0; i < parents.length; i++) {
- aService._logger.debug("removing from parent " + i);
- parents[i].children.remove(acctCoopObj);
- }
- // kill the account node
- aService._logger.debug("destroying account " + aAccountUrn);
- acctCoopObj.destroy();
-
- // Finally, slowly delete the bookmarks
- var synchronize = function OFBE_removeAccount_sync(should_yield) {
- var i = 0;
- var bmChildren = bmStream.children.enumerate();
- while (bmChildren.hasMoreElements()) {
- var tag = bmChildren.getNext();
- var enum_ = tag.children.enumerate();
- while (enum_.hasMoreElements()) {
- var bm = enum_.getNext();
- aService._logger.debug("destroying bookmark " + bm.URL);
- var parents = bm.getParents();
- for (var j = 0; j < parents.length; j++) {
- parents[j].children.remove(bm);
- }
- bm.destroy();
- if (should_yield()) {
- yield;
- }
- }
- }
- bmStream.destroy();
- };
-
- if (bmStream) {
- FlockScheduler.schedule(null, 0.1, 10, synchronize);
- }
- };
-
- onlineFavoritesBackend.updateBookmark =
- function OFBE_updateBookmark(aService, aAccountUrn, aServerBookmark, aPrivate) {
- var bookmark_urn = aAccountUrn + ":" + aServerBookmark.URL;
- var localBookmark = null;
- var tagList;
- var i;
-
- // Create/update the bookmark itself
- if (aService._coop.Bookmark.exists(bookmark_urn)) {
- // Need to check if any modification is needed before we assert anything
- localBookmark = aService._coop.get(bookmark_urn);
- if (bookmarks_match(aServerBookmark, localBookmark)) {
- aService._logger.debug("Unchanged on server: Ignoring "
- + aServerBookmark.URL);
- return;
- }
- aService._logger.debug("Modified on server : Updating "
- + aServerBookmark.URL);
- if (stringify(aServerBookmark.name) !== stringify(localBookmark.name)) {
- localBookmark.name = aServerBookmark.name;
- }
- if (stringify(aServerBookmark.description) !==
- stringify(localBookmark.description))
- {
- localBookmark.description = aServerBookmark.description;
- }
- if (sanitizeTags(aServerBookmark.tags) !==
- sanitizeTags(localBookmark.tags))
- {
- localBookmark.tags = sanitizeTags(aServerBookmark.tags);
- var tagenum = localBookmark.tag.enumerate();
- while (tagenum.hasMoreElements()) {
- var tag = tagenum.getNext();
- localBookmark.tag.remove(tag);
- }
- }
- var date = new Date();
- localBookmark.LastModifiedDate = date;
- localBookmark.private = aPrivate;
- } else {
- // New bookmark
- aService._logger.debug("New on server : Creating "
- + aServerBookmark.URL);
- localBookmark = new aService._coop.Bookmark(bookmark_urn, {
- URL: aServerBookmark.URL,
- name: aServerBookmark.name,
- description: aServerBookmark.description,
- tags: aServerBookmark.tags,
- datevalue: aServerBookmark.datevalue,
- hash: aServerBookmark.hash,
- flockType: "bookmark",
- private: aPrivate,
- isPollable: false
- });
- // bookmarks.children.add(localBookmark);
- }
- tagList = aServerBookmark.tags.split(/[\s,]/);
- for (i = 0; i < tagList.length; i++) {
- localBookmark.tag.addOnce(tagList[i]);
- }
- var bookmarks = aService._coop.get(aAccountUrn + ":bookmarks");
- this.classifyBookmark(aService, bookmarks, localBookmark, tagList);
- };
-
- onlineFavoritesBackend.classifyBookmark =
- function OFBE_classifyBookmark(aService, aBookmarks,
- aLocalBookmark, aTagList) {
- var i;
- // Delete the bookmark from the tag folders, and delete empty tags
- var parents = aLocalBookmark.getParents();
- while (parents.length > 0) {
- var parent_ = parents.pop();
- parent_.children.remove(aLocalBookmark);
- if (!parent_.children.count()) {
- aBookmarks.children.remove(parent_);
- parent_.destroy();
- }
- }
-
- var tagFolder;
- // Add the bookmark to the tag folders it should be
- if ((aTagList.length === 1 && !aTagList[0].length) ||
- (!aTagList.length) ||
- (aTagList === [""]))
- {
- var noTagUrn = aBookmarks.id() + ":notag";
- tagFolder = aService._coop.get(noTagUrn);
- tagFolder.children.add(aLocalBookmark);
- } else {
- for (i = 0; i < aTagList.length; i++) {
- var tagUrn = aBookmarks.id() + ":tag:" + aTagList[i];
- if (aService._coop.Folder.exists(tagUrn)) {
- tagFolder = aService._coop.get(tagUrn);
- } else {
- tagFolder = this.createTag(aService, aBookmarks, aTagList[i], tagUrn);
- }
- tagFolder.children.add(aLocalBookmark);
- }
- }
- };
-
- onlineFavoritesBackend.destroyBookmark =
- function OFBE_destroyBookmark(aService, aAccountId, aUrl) {
- var bookmark_urn = aService.urn + ":" + aAccountId + ":" + aUrl;
-
- if (aService._coop.Bookmark.exists(bookmark_urn)) {
- var bookmarks = aService._coop.get(aService.urn + ":"
- + aAccountId + ":bookmarks");
- var bookmark = aService._coop.get(bookmark_urn);
-
- bookmarks.children.remove(bookmark);
- bookmark.destroy();
- }
- };
-
- onlineFavoritesBackend.updateLocal =
- function OFBE_updateLocal(aService, aPostsList, aLastUpdate, aAccountUrn) {
- var i;
- var bmEnum;
- var bmEnum2;
- // Update the last update time for the bookmark stream
- var localBookmarks = aService._coop.get(aAccountUrn + ":bookmarks");
- localBookmarks.last_update_time = aLastUpdate;
-
- var be = this;
- var synchronize = function OFBE_updateLocal_sync(should_yield) {
- var urlHash = {}; // Useful to optimize deletion
-
- // Create new bookmarks, or update existing bookmarks
- for (i = 0; i < aPostsList.length; i++) {
- if (aPostsList[i].tags === "system:unfiled") {
- aPostsList[i].tags = "";
- }
- // To optimize deletion: put the URLs in a hash
- urlHash[aPostsList[i].URL] = true;
- be.updateBookmark(aService, aAccountUrn, aPostsList[i]);
- if (should_yield()) {
- yield;
- }
- }
-
- // Remove locally bookmarks deleted on the server
- var localLength = 0;
- i = 0;
- bmEnum = localBookmarks.children.enumerate();
- while (bmEnum.hasMoreElements()) {
- var localTag = bmEnum.getNext();
- bmEnum2 = localTag.children.enumerate();
- while (bmEnum2.hasMoreElements()) {
- var localBookmark = bmEnum2.getNext();
- if (!urlHash[localBookmark.URL]) {
- aService._logger.debug("Deleted on server : Deleting "
- + localBookmark.URL);
- var parents = localBookmark.getParents();
- for (var j = 0; j < parents.length; j++) {
- parents[j].children.remove(localBookmark);
- }
- localBookmark.destroy();
- }
- }
- if (should_yield()) {
- yield;
- }
- }
-
- // Remove empty tags
- bmEnum = localBookmarks.children.enumerate();
- while (bmEnum.hasMoreElements()) {
- var tag = bmEnum.getNext();
- bmEnum2 = tag.children.enumerate();
- if (!bmEnum2.hasMoreElements() &&
- (tag.id() !== localBookmarks.id() + ":notag"))
- {
- // The tag is empty, let's delete it.
- // Note: Don't delete "No Tag".
- localBookmarks.children.remove(tag);
- tag.destroy();
- }
- }
- };
-
- FlockScheduler.schedule(null, 0.1, 10, synchronize);
- };
-
- onlineFavoritesBackend.createTag =
- function OFBE_createTag(aService, aBookmarks, aTag, aTagUrn) {
- var tagFolder = new aService._coop.Folder(aTagUrn,
- { name: aTag }
- );
- var enum_ = aBookmarks.children.enumerate();
- var found = false;
- var i = 1;
- enum_.getNext(); // Ignore "notag"
- while (enum_.hasMoreElements() && !found) {
- var currentTag = enum_.getNext();
- if (aTag < currentTag.name) {
- found = true;
- aBookmarks.children.insertAt(tagFolder, i + 1);
- }
- i++;
- }
- if (!found) {
- aBookmarks.children.add(tagFolder);
- }
- return tagFolder;
- };
-
- onlineFavoritesBackend.updateTags =
- function OFBE_updateTags(aService, aAccountId, aTags) {
- // Copy aTags, so we can modify it.
- var tags = [];
- var tag;
- var i;
- for (i = 0; i < aTags.length; i++) {
- tags.push(aTags[i]);
- }
- // Remove tags no longer present.
- var localBookmarks = aService._coop.get(aService.urn + ":"
- + aAccountId + ":bookmarks");
- var tagenum = localBookmarks.tag.enumerate();
- while (tagenum.hasMoreElements()) {
- tag = tagenum.getNext();
- if (tags.indexOf(tag) < 0) {
- // Not in new array, so remove it.
- localBookmarks.tag.remove(tag);
- } else {
- // Already there, remove from input so we don't try adding it again.
- tags.splice(tags.indexOf(tag), 1);
- }
- }
- // Put in the net new tags.
- for (i = 0; i < tags.length; i++) {
- localBookmarks.tag.addOnce(tags[i]);
- }
- };
-
- onlineFavoritesBackend.showNotification =
- function OFBE_showNotification(aMessage) {
- var wm = CC["@mozilla.org/appshell/window-mediator;1"]
- .getService(CI.nsIWindowMediator);
- var topNavWindow = wm.getMostRecentWindow("navigator:browser");
-
- var nBox = topNavWindow.gBrowser.getNotificationBox();
- var notification = nBox.getNotificationWithValue("favorite-error");
- if (notification) {
- notification.label = aMessage;
- } else {
- nBox.appendNotification(aMessage,
- "favorite-error",
- "chrome://browser/skin/Info.png",
- nBox.FLOCK_PRIORITY_HIGH,
- null);
- }
- };
-